package com.titan.core.utils.dbinfo;

import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;

import com.titan.core.utils.db.DBUtils;
import com.titan.core.utils.dbinfo.bean.ColumnBean;
import com.titan.core.utils.dbinfo.bean.TableBean;
import com.titan.core.utils.dbinfo.impl.TableInfoMysqlImpl;
import com.titan.core.utils.dbinfo.impl.TableInfoOracleImpl;
import com.titan.core.utils.dbinfo.impl.TableInfoSqlImpl;
import com.titan.core.utils.dbinfo.interfaces.TableInfo;


/**
 * @author 周成功
 * @email 86898837@qq.com
 * @date 2020年02月14日
 */
public class TableInfoUtil {
    public static void registerJdbcDriver(String dbDriver) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException {
        DBUtils.registerDriver(dbDriver);
    }
    
    public static TableBean getTableInfo(String dbDriver, String dbUrl, String dbName, String dbUserid, String dbPassword, String tablename) throws Exception {
        registerJdbcDriver(dbDriver);
        
        TableInfo database =null;
        if(database==null) {
            for (int i = 0; i < DBInfoGlobals.DATABASE_DRIVER_ORACLE.length; i++) {
                if(dbDriver.equalsIgnoreCase(DBInfoGlobals.DATABASE_DRIVER_ORACLE[i])) {
                    database = new TableInfoOracleImpl();
                    break;
                }
            }
        }
        if(database==null) {
            for (int i = 0; i < DBInfoGlobals.DATABASE_DRIVER_MYSQL.length; i++) {
                if(dbDriver.equalsIgnoreCase(DBInfoGlobals.DATABASE_DRIVER_MYSQL[i])) {
                    database = new TableInfoMysqlImpl();
                    break;
                }
            }
        }
        if(database!=null) {
            Connection conn =null;
            try {
                conn = DBUtils.getConnection(dbUrl, dbUserid, dbPassword);
                return getTableInfo(conn, dbName, database, tablename);
            } finally {
                DBUtils.close(conn);
            }
        }
        return null;
    }
    public static TableBean getTableInfo(Connection conn, Integer dbtype, String tablename) throws Exception {
        return getTableInfo(conn, dbtype, null, tablename);
    }
    public static TableBean getTableInfo(Connection conn, Integer dbtype, String dbName, String tablename) throws Exception {
        TableInfo database =null;
        if(dbtype.equals(DBInfoGlobals.DATABASE_TYPE_ORACLE)) {
            database = new TableInfoOracleImpl();
        } else if(dbtype.equals(DBInfoGlobals.DATABASE_TYPE_MYSQL)) {
            database = new TableInfoMysqlImpl();
        } else if(dbtype.equals(DBInfoGlobals.DATABASE_TYPE_SQL)) {
            database = new TableInfoSqlImpl();
        }
        if(database!=null) {
            return getTableInfo(conn, dbName, database, tablename);
        }
        return null;
    }
    
    
    private static TableBean getTableInfo(Connection conn, String dbName, TableInfo database, String tablename) throws Exception {
        TableBean table = new TableBean();
        table.setNameEn(tablename);

        // 获得表信息
        // 表类型, 表注释
        String[] tableInfo =database.getTableInfo(conn, dbName, tablename);
        if(tableInfo!=null) {
            String[] comments =analyze(tableInfo[1], tablename);
            table.setNameZh(comments[0]);
            table.setComments(comments[1]);
            table.setType(tableInfo[0]);
        }
        
        // 获得主键列
        String[] key =database.getPrimaryKey(conn, dbName, tablename);
        table.setPrimaryKey(key);
        
        String[][] indexs = database.getUniqueIndex(conn, dbName, tablename);
        table.setUniqueIndex(indexs);
        
        // 获得列信息
        // {列英文名, 数据类型, 数据长度, 数值指定长度(整数+小数), 数值小数部分长度, 是否可以为null(Y/N), 列注释}
        String[][] columnInfo =database.getColumnInfo(conn, dbName, tablename);
        ColumnBean[] columns = new ColumnBean[columnInfo.length];
        for (int row = 0; row < columnInfo.length; row++) {
            String[] comments = analyze(columnInfo[row][6], columnInfo[row][0]);
            columns[row] = new ColumnBean();
            columns[row].setTablename(tablename);
            columns[row].setNameZh(comments[0]);
            columns[row].setComments(comments[1]);
            columns[row].setNameEn(columnInfo[row][0]);
            columns[row].setSqltype(columnInfo[row][1]);
            columns[row].setDatalength(Integer.parseInt(columnInfo[row][2]));
            columns[row].setDataprecision(Integer.parseInt(columnInfo[row][3]));
            columns[row].setDatascale(Integer.parseInt(columnInfo[row][4]));
            columns[row].setNullable(columnInfo[row][5]);
        }
        table.setColumns(columns);
        return table;
    }
    

    /**
     * 将数据库注释中非法字符替换成相应的合法字符
     *
     * @param sour 要替换的注释串
     * @return 替换后的字符串
     */
    private static String replate(String sour) {
        String dest = sour == null ? "" : sour;
        dest = dest.replaceAll("\\\\", "\\\\\\\\");
        dest = dest.replaceAll("\\r", " ");
        dest = dest.replaceAll("\\n", " ");
        dest = dest.replaceAll("\"", "”");
        return dest;
    }


    /**
     * 将数据库注释分解成中文名称和说明两个部分
     *
     * @param comments 要分解的字符串
     * @return 分解后的结果 {中文名称, 说明}
     */
    public static String[] analyze(String comments, String defaultStr) {
        if((comments==null)||(comments.trim().equals(""))) {
            return new String[]{defaultStr, defaultStr};
        }
        comments =replate(comments);
        String[] result =new String[2];
        if(comments.indexOf(",") > 0) {
            result[0] = comments.substring(0, comments.indexOf(","));
        } else if(comments.indexOf("，") > 0) {
            result[0] = comments.substring(0, comments.indexOf("，"));
        } else if(comments.indexOf(" ") > 0) {
            result[0] = comments.substring(0, comments.indexOf(" "));
        } else {
            result[0] = comments;
        }
        result[1] = comments;
        return result;
    }
    

    /**
     * 根据数据库表名生成域对象类名
     *
     * @param tablename 要转换的数据库表名称
     * @return 转换后的类对象名
     */
    public static String tablenameToFilename(String tablename) {
        String dtoName = "";
        String[] fieldTablename = tablename.split("_");
        for (int i = 0; i < fieldTablename.length; i++) {
            dtoName = dtoName + fieldTablename[i].substring(0, 1).toUpperCase() + fieldTablename[i].substring(1, fieldTablename[i].length()).toLowerCase();
        }
        return dtoName;
    }

    
    /**
     * 根据数据库表列名生成域对象属性名
     *
     * @param fieldname 要转换生成的数据库列表
     * @return
     */
    public static String fieldnameToProperty(String fieldname) {
        String dtoName = "";
        String[] field = fieldname.split("_");
        for (int i = 0; i < field.length; i++) {
            dtoName = dtoName + field[i].substring(0, 1).toUpperCase() + field[i].substring(1, field[i].length()).toLowerCase();
        }
        dtoName =dtoName.substring(0, 1).toLowerCase() + dtoName.substring(1);
        return dtoName;
    }
    
    
    public static String packageToFile(String packagepath, String prefix) {
        String newFilePath = prefix;
        if (!newFilePath.endsWith(File.separator)) {
            newFilePath = newFilePath + File.separator;
        }
        String[] filepath = packagepath.split("\\.");
        for (int i = 0; i < filepath.length; i++) {
            newFilePath = newFilePath + filepath[i];
            if (i < (filepath.length - 1)) {
                newFilePath = newFilePath + File.separator;
            } else {
                newFilePath = newFilePath + ".java";
            }
        }
        return newFilePath;
    }

    // 根据全类路径得到类名
    public static String packageToClassname(String packagepath) {
        return packagepath.substring(packagepath.lastIndexOf(".")+1);
    }


    public static String pathToPackage(String filepath) {
        String packagepath = "";
        String filepathtmp = "";
        int pos =filepath.lastIndexOf("com\\ytincl\\");
        if(pos>=0) {
            filepathtmp = filepath.substring(pos);
        } else {
            pos =filepath.lastIndexOf("org\\zzz\\");
            filepathtmp = filepath.substring(pos);
        }
        String[] filepathname = filepathtmp.split("\\\\");
        for (int i = 0; i < filepathname.length; i++) {
            if(filepathname[i].trim().length()==0) {
                continue;
            }
            if (packagepath.equals("")) {
                packagepath = packagepath + filepathname[i];
            } else {
                packagepath = packagepath + "." + filepathname[i];
            }
        }
        return packagepath;
    }


//    public static String packageToSdto(String packagepath) {
//        String sdtopath = packagepath.substring(0, packagepath.lastIndexOf("."));
//        sdtopath = sdtopath + JDTGlobals.FILE_POSTFIX_SDTO.toLowerCase();
//        return sdtopath;
//    }


    // 将两个数组链接起来
    public static String[] linkArray(String[] array1, String[] array2) {
        if((array1==null)&&(array2==null)) {
            return new String[0];
        }
        if(array1==null)  return array2;
        if(array2==null)  return array1;
        String[] array3 =new String[array1.length+array2.length];
        System.arraycopy(array1, 0, array3, 0, array1.length);
        System.arraycopy(array2, 0, array3, array1.length, array2.length);
        return array3;
    }

    // 将数组元素转换成小写。
    public static String[] toLowerCaseArray(String[] array) {
        if(array==null)  return array;
        String[] newArray=new String[array.length];
        for (int i = 0; i < array.length; i++) {
            newArray[i] =array[i].toLowerCase();
        }
        return newArray;
    }
//    // 向数组中增加一个元素
//    public static SDTO[] addArray(SDTO[] array, SDTO object) {
//        if(array==null)  return new SDTO[]{object};
//        SDTO[] newArray=new SDTO[array.length+1];
//        System.arraycopy(array, 0, newArray, 0, array.length);
//        newArray[array.length] =object;
//        return newArray;
//    }
    
}
